﻿/*!	@file	r_gui_draw.h
	@brief	GUI描画クラス
Copyright (c) 2010 Yuya Yamaguchi

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef _R_GUI_DRAW_H_
#define _R_GUI_DRAW_H_

#include "../math/r_math_colorRGBi.h"
#include "../math/r_math_vector2.h"
#include "../math/r_math_vector3.h"
#include "../util/r_util_doublebuffer.h"
#include "../resource/r_resource.h"
#include <vector>

namespace r{
	namespace draw{
		class VertexBuffer;
		class ConstantBuffer;
		class InputLayout;
		class VertexShader;
		class PixelShader;
		class Sampler;
		class RasterizerState;
		class BlendState;
		class DepthStencilState;
	}
	namespace gui{
		class Server;
	}
	namespace resource{
		class ResourceTexture;
	}
}

namespace r{
	namespace gui{
		namespace draw{
			enum BufferSize {
				BufferSize_MaxVertexNum = 3 * 2 * 5120		//!< 5K枚の矩形描画
			};

			//! フォントコード
			enum FontWriteCode {
				FontWriteCode_doOutPut = 0,
				FontWriteCode_doSpace,
				FontWriteCode_doCR,
				FontWriteCode_Nop
			};

			//! フォント検索領域
			struct FontRange {
				r_ui16					from;
				r_ui16					to;
				r_ui16					offset;
			};
			//! フォントコード対応情報
			struct FontInfo {
				r_ui16					writeable	: 2;
				r_ui16					code		: 14;
			};
			//! フォントデータ
			struct FontData {
				r::math::Vector2D				uv1;
				r::math::Vector2D				uv2;
			};
			struct FontFile {
				r_ui32					numRange;
				r_f32					fontSpace;
				r_f32					fontWidth;
				r_f32					fontHeight;
				union {
					FontRange*	range;
					r_ui64					__64_1;
				};
				union {
					FontInfo*		info;
					r_ui64					__64_2;
				};
				union {
					FontData*		data;
					r_ui64					__64_3;
				};
			};

			struct Vertex {
				r::math::Vector3D		pos;
				r::math::Vector2D		uv;
				r::math::ColorRGBi		color;
			};

			//! guiパーツとして組み込まれているアイコン情報
			enum Icons {
				Icons_Close		= 0,	//!< 閉じる
				Icons_Mini,				//!< 最小化
				Icons_Max,					//!< 最大化
				Icons_Check,				//!< チェックマーク
				Icons_OpenBox,				//!< クリックで開くためのボックス
				Icons_CloseBox,			//!< クリックで閉じるためのボックス
				Icons_Triangle,			//!< 三角形下
				Icons_Spin,				//!< スピン用アイコン
				Icons_Eye,					//!< 目玉アイコン
				Icons_Link,				//!< リンクアイコン
				Icons_Play,				//!< 再生
				Icons_Pause,				//!< 一時停止
				Icons_Lock,				//!< ロック
				Icons_Key,					//!< 鍵
				Icons_SpotLight,			//!< スポットライト
				Icons_PointLight,			//!< ポイントライト
				Icons_DirLight,			//!< ディレクショナルライト
				Icons_Camera,				//!< カメラ
				Icons_Null,				//!< Null
				Icons_Chara,				//!< キャラクタ
				Icons_Term
			};

			//! iconパーツの回転指定
			enum IconsRotate {
				IconsRotate_0,				//!< 回転なし
				IconsRotate_90,			//!< 右回転
				IconsRotate_270,			//!< 左
				IconsRotate_180			//!< 上下
			};

			//! guiパーツに組み込まれているwindow情報
			enum WIndows {
				WIndows_Window		= 0,	//!< 通常ウィンドウ
				WIndows_FlatBox,			//!< 平面ボックス
				WIndows_FlatArc,			//!< 平面丸ボックス
				WIndows_FlatLArc,			//!< 平面左丸ボックス
				WIndows_FlatRArc,			//!< 平面右丸ボックス
				WIndows_DownBox,			//!< 凹ボックス
				WIndows_DownArc,			//!< 凹丸ボックス
				WIndows_DownLArc,			//!< 凹左丸ボックス
				WIndows_DownRArc,			//!< 凹右丸ボックス
				WIndows_UpBox,				//!< 凸ボックス
				WIndows_UpArc,				//!< 凸丸ボックス
				WIndows_UpLArc,			//!< 凸左丸ボックス
				WIndows_UpRArc,			//!< 凸右丸ボックス
				WIndows_Term
			};

			//! 矩形描画用の構造体
			struct Rect {
				//! 左上座標
				r_si32			x;
				r_si32			y;
				//! 幅
				r_ui32			width;
				r_ui32			height;
				//! UVの左上
				r_f32			uvX;
				r_f32			uvY;
				//! UVの幅
				r_f32			uvWidth;
				r_f32			uvHeight;
			};


			//! GUI用描画バッファクラス
			/*!
			頂点フォーマットはVertexに固定されます
			描画の前にsetRect関数で領域を書き込み可能にして下さい
			*/
			class Draw
			{
				friend class r::gui::Server;
				typedef	std::vector<r::draw::VertexBuffer*>	vbuffer_array;

				struct stRGUIDrawIconInfo {
					r_f32		size[2];
					r_f32		uvmin[2];
					r_f32		uvmax[2];
				};
				struct stRGUIDrawWindowInfo {
					r::math::Vector2D		size;
					struct rec {
						r::math::Vector2D	min;
						r::math::Vector2D	max;
					} rects[9];
				};
			protected:
				Draw();
				~Draw();
			public:
				// システム呼び出し
				//! バッファのスワップ等
				/*!
				*/
				void			update();
				//! GUI描画用の設定をする
				/*!
				*/
				void			begin();
			public:
				//! テキストの描画を実行する
				/*! 実行タイミングでGUIの描画コマンドリストに積み込まれます
				*/
				void			drawText ( r_si32 x, r_si32 y, const r_cstr text, const r::math::ColorRGBi color );
				void			drawText ( r_si32 x, r_si32 y, const r_cstr text, const r::math::ColorRGBi color, const r::math::ColorRGBi shadowcolor );
				//! 特定テキストのn文字目のピクセル位置を取得
				/*!
				@param	text	[in]	評価テキスト文字列
				@param	pos		[in]	評価文字位置
				@param	off		[off]	ピクセル位置
				*/
				void			calcTextPixPos ( const r_cstr text, r_ui32 pos, r::math::Vector2D& off );
				//! テキストの矩形サイズを取得
				/*!
				@param	text	[in]	評価テキスト文字列
				@param	max		[off]	ピクセル最大値
				*/
				void			calcTextPixSize ( const r_cstr text, r::math::Vector2D& max );
				//! GUI用テクスチャをセットする
				/*!
				*/
				void			asignGUITexture();
				//! テクスチャリソースをセットする
				/*!
				*/
				void			asignTextureResource( r::resource::ResourcePtr tex );
				//! シェーダをテクスチャ用に設定する
				/*!
				*/
				void			asignGUIDefaultShader();
				//! シェーダをコンスタント出力に設定する
				/*!
				*/
				void			asignGUIConstantShader();
				//! アイコンを描画する
				/*!
				*/
				void			drawIcon ( r_si32 x, r_si32 y, r_si32 icons, const r::math::ColorRGBi color, r_si32 rotate = IconsRotate_0 );
				//! windowを描画する
				/*!
				*/
				void			drawWindow ( r_si32 x, r_si32 y, r_si32 w, r_si32 h, r_si32 windows, const r::math::ColorRGBi color );
				//! 矩形描画を実行する
				/*!
				*/
				void			drarwRect ( const Rect& rect, const r::math::ColorRGBi color );
				//! 頂点配列の描画を実行します
				/*!
				*/
				void			drawVertexTriList ( const Vertex* varray, r_ui32 vertexNum );
				//! 描画エリアのZバッファを設定します
				/*!
				*/
				void			setRect ( r_si32 x, r_si32 y, r_si32 w, r_si32 h );
				//! 最後に設定された描画エリアを取得します
				/*!
				*/
				void			getRect ( r_si32& x, r_si32& y, r_si32& w, r_si32& h ) const;
				///	描画エリアのZバッファを有効にします
				/*!
				*/
				void			asignRect();
				//! 描画エリアのネスト計算を行う
				/*!
				@retval	false	そもそも全ての範囲が表示できない
				*/
				r_bool			calcRect ( r_si32 px, r_si32 py, r_si32 pw, r_si32 ph, r_si32 cx, r_si32 cy, r_si32 cw, r_si32 ch, r_si32& x, r_si32& y, r_si32& w, r_si32& h ) const;
				//! 描画用深度値を設定する
				/*!
				*/
				void			setZ ( r_si32 z );
				//! 深度値を取得する
				/*!
				*/
				r_si32			getZ() const;
				//! 深度値を取得する
				/*!
				*/
				r_f32			getFloatZ() const;

				//! GUIテクスチャでのUVサイズの計算
				r_f32			pix2uv ( r_si32 val ) const;
			protected:
				//! 深度テストを設定する
				/*!
				*/
				void			setDepthTestAlways();
				void			setDepthTestEqual();
			private:
				//! 深度値(整数)
				r_si32						guiZInt;
				//! 深度値(float)
				r_f32						guiZFloat;
				//! 矩形
				r_si32						guiRectX;
				r_si32						guiRectY;
				r_si32						guiRectW;
				r_si32						guiRectH;
				//! 描画用シェーダ
				r::draw::VertexShader*		guiVShader;
				//! 描画用シェーダ
				r::draw::PixelShader*		guiPShader;
				// テクスチャ無しベタ塗り
				//! 描画用シェーダ
				r::draw::VertexShader*		guiConstVShader;
				//! 描画用シェーダ
				r::draw::PixelShader*		guiConstPShader;

				//! フォント用テクスチャ
				r::resource::ResourcePtr				guiFontTexturePtr;
				r::resource::ResourceTexture*			guiFontTexture;
				//! ウィンドウ用テクスチャ
				r::resource::ResourcePtr				guiWidgetTexturePtr;
				r::resource::ResourceTexture*			guiWidgetTexture;
				//! 頂点レイアウト
				r::draw::InputLayout*		guiInputLayout;
				//! サンプラ
				r::draw::Sampler*			guiSampler;
				//! ラスタライザステート
				r::draw::RasterizerState*	guiRaster;
				//! ブレンドステート
				r::draw::BlendState*		guiBlend;
				//! 深度ステンシルステート
				r::draw::DepthStencilState*	guiDepthStateEqual;
				r::draw::DepthStencilState*	guiDepthStateOverwrite;
				r::draw::DepthStencilState*	guiDepthStateCash;

				//! コンスタントバッファ(変換行列)
				r::draw::ConstantBuffer*		guiConstant;

				//! 頂点データ
				r_tm_doubleBuffer<vbuffer_array>	removeBuffer;
				//! フォントマップデータ
				FontFile*			fontData;
			private:
				//! iconデータ
				stRGUIDrawIconInfo			iconinfo[Icons_Term];
				//! windowデータ
				stRGUIDrawWindowInfo		windowinfo[WIndows_Term];
			private:
				// コピー禁止
				Draw ( const Draw& src );
				Draw&	operator = ( const Draw& src );
			};
		}
	}
}


#endif // _R_GUI_DRAW_H_


